﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;

namespace NEATlib
{
    public class DataCollection
    {
        protected List<DataItem> _dataCollection = null;

        public DataCollection()
        {
            _dataCollection = new List<DataItem>();
        }

        public DataCollection(List<DataItem> dataCollection)
        {
            _dataCollection = new List<DataItem>(dataCollection);
        }

        public int SamplesCount
        {
            get { return _dataCollection.Count; }
        }

        public DataItem this[int index]
        {
            get { return _dataCollection[index]; }
        }

        public DataCollection Clone()
        {
            return new DataCollection(_dataCollection);
        }

        public void Concat(DataCollection otherCollection)
        {
            _dataCollection.AddRange(otherCollection._dataCollection);
        }

        public DataCollection GetDiffPart(DataCollection otherCollection)
        {
            if (otherCollection.SamplesCount > _dataCollection.Count - 1)
                throw new ArgumentOutOfRangeException("otherCollection");

            var newcollection =
                _dataCollection.Where(item => otherCollection._dataCollection.IndexOf(item) < 0).ToList();

            return new DataCollection(newcollection);
        }

        public DataCollection GetPart(int startPos, int endPos)
        {
            if (startPos < 0 || startPos > _dataCollection.Count - 2)
                throw new ArgumentOutOfRangeException("startPos");
            if (endPos < 1 || endPos > _dataCollection.Count)
                throw new ArgumentOutOfRangeException("endPos");

            return new DataCollection(_dataCollection.GetRange(startPos, endPos - startPos));
        }

        public DataCollection GetRandomPart(int count)
        {
            if (count > _dataCollection.Count - 1)
                throw new ArgumentOutOfRangeException("count");

            var newcollection = new List<DataItem>();
            var rand = new Random();
            while (newcollection.Count < count)
            {
                var pos = rand.Next(_dataCollection.Count - 1);
                if (newcollection.IndexOf(_dataCollection[pos]) < 0)
                    newcollection.Add(_dataCollection[pos]);
            }

            return new DataCollection(newcollection);
        }

        public virtual void LoadData(string[] lines)
        {
        }

        public double[][] OutputToArray()
        {
            var result = new double[_dataCollection.Count][];
            for (int i = 0; i < _dataCollection.Count; i++)
            {
                result[i] = _dataCollection[i].ExpectedOutput;
            }
            return result;
        }

        public double[][] ToArray()
        {
            var result = new double[_dataCollection.Count][];
            for (int i = 0; i < _dataCollection.Count; i++)
            {
                result[i] = _dataCollection[i].DataSeries;
            }

            return result;
        }
    }

    public class TimeSeriesDataCollection : DataCollection
    {
        public TimeSeriesDataCollection LoadData(string filename, int seriesLength)
        {
            var series = ReadCSVFile(filename);
            var collectionSize = series.Count() - seriesLength;
            for (var i = 0; i < collectionSize; i++)
            {
                var cursValues = new double[seriesLength];
                for (var j = 0; j < seriesLength; j++)
                {
                    cursValues[j] = series[i + j];
                }

                var expectedVal = new double[] {series[i + seriesLength]};

                _dataCollection.Add(new DataItem
                {
                    DataSeries = cursValues,
                    ExpectedOutput = expectedVal
                });
            }
            return this;
        }

        private static double[] ReadCSVFile(string fileName)
        {
            string[] lines = File.ReadAllLines(fileName);
            var result = new double[lines.Count()];
            for (int i = 0; i < lines.Count(); i++)
                Double.TryParse(lines[i].Split(';')[5],
                    System.Globalization.NumberStyles.Float,
                    System.Globalization.CultureInfo.GetCultureInfo("en"), out result[i]);


            return result;
        }

        public DataCollection LoadLearnData(string eurusdCSV, int seriesLength)
        {
            LoadData(eurusdCSV, seriesLength);
            return GetPart(0, (int) (SamplesCount*0.8));
        }

        public DataCollection LoadTestData(string eurusdCSV, int seriesLength)
        {
            LoadData(eurusdCSV, seriesLength);
            return GetPart((int) (SamplesCount*0.8), SamplesCount - 1);
        }
    }
}


